home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / graphics.17 / graphics / graphics-0.17 / plot2plot / plot2.c < prev   
Encoding:
C/C++ Source or Header  |  1991-03-12  |  15.9 KB  |  643 lines

  1. /* plot2plot, a utility for converting Unix plot files into postscript.
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. Plot2plot is distributed in the hope that it will be useful, but WITHOUT ANY
  5. WARRANTY.  No author or distributor accepts responsibility to anyone for the
  6. consequences of using it or for whether it serves any particular purpose or
  7. works at all, unless he says so in writing.  Refer to the GNU General Public
  8. License for full details.
  9.  
  10. Everyone is granted permission to copy, modify and redistribute plot2plot, but
  11. only under the conditions described in the GNU General Public License.  A copy
  12. of this license is supposed to have been given to you along with plot2plot so
  13. you can know your rights and responsibilities.  It should be in a file named
  14. COPYING.  Among other things, the copyright notice and this notice must be
  15. preserved on all copies.  */
  16.  
  17. /* This file is the main routine for plot2plot.
  18.  
  19.    It includes code to read the plot file and call plot functions
  20.    to draw the graphics. */
  21.  
  22. #include "sys-defines.h"
  23. #include "libplot.h"
  24. #include "getopt.h"
  25. #include "../COPYING"
  26.  
  27. /* Long options we recognize */
  28.  
  29. #define    ARG_NONE    0
  30. #define    ARG_REQUIRED    1
  31. #define    ARG_OPTIONAL    2
  32.  
  33. struct option    long_options[] = {
  34.     { "backward-compatible", ARG_NONE, NULL, 'b' },
  35.     { "input-is-ascii", ARG_NONE, NULL, 'i' },
  36.     { "output-as-ascii", ARG_NONE, NULL, 'o' },
  37.     { "high-byte-first", ARG_NONE, NULL, 'h' },
  38.     { "low-byte-first", ARG_NONE, NULL, 'l' },
  39.     { "signed-input", ARG_NONE, NULL, 's' },
  40.     { "unsigned-input", ARG_NONE, NULL, 'u' },
  41.     { "warranty", ARG_NONE, NULL, 'W' },
  42.     { "copying", ARG_NONE, NULL, 'C' },
  43.     { "help", ARG_NONE, NULL, 'H' },
  44.     { "version", ARG_NONE, NULL, 'V' },
  45.     { NULL, 0, NULL, 0}
  46. };
  47.     
  48. enum plot_instruction
  49. {
  50.   ALABEL =    'T',
  51.   ARC =        'a',
  52.   CIRCLE =    'c',
  53.   COLOR =    'C',
  54.   COMMENT =    '#',
  55.   CONT =    'n',
  56.   ERASE =    'e',
  57.   FILL =    'L',
  58.   FONT =    'F',
  59.   FONTSIZE =    'S',
  60.   LABEL =    't',
  61.   LINE =    'l',
  62.   LINEMOD =    'f',
  63.   MOVE =    'm',
  64.   POINT =    'p',
  65.   ROTATE =    'r',
  66.   SPACE =    's',
  67. };
  68.  
  69. /* a non-zero value specifies that the output be compatible with standard
  70.    plot filters which do not support the GNU extensions such as
  71.    adjusted labels. */
  72. int backward_compatible = 0;
  73.  
  74. /* a non-zero value specifies that the input is in an ascii format.
  75.    all strings and coordinates are preceded by a space and coordinates
  76.    in ascii rather than binary. */
  77. int ascii_input = 0;
  78.  
  79. /* a non-zero value specifies that the output is in an ascii format.
  80.    all strings and coordinates are preceded by a space and coordinates
  81.    in ascii rather than binary. */
  82. int ascii_output = 0;
  83.  
  84. /* This flag specifies that the input contains unsigned (if zero) or
  85.    signed (if nonzero) two byte intgers. The default is signed. */
  86. int signed_input = 1;
  87.  
  88. /* read in two byte intgers with high_byte_first. The default is to read the low
  89.    byte first. */
  90. int high_byte_first = 0;
  91.  
  92. /* guess_byte_order is a flag which, if non-zero, indicated that the function
  93.    find_byte_order should be used to guess the byte order for the input file. */
  94. int guess_byte_order = 1;
  95.  
  96. /* swap_bytes returns the bottom two bytes of its integer argument with
  97.    their bytes reversed. */
  98.  
  99. int
  100. swap_bytes (x)
  101.      int x;
  102. {
  103.   unsigned char a, b;
  104.   a = x & 0xff;
  105.   b = (x >> 8) & 0xff;
  106.   return ((a << 8)|b);
  107. }
  108.  
  109. /* This is a set of known values for the maximum x (abscissa) values
  110.    specified in the plot size command for known devices.  Using this
  111.    set we can construct a heuristic proceedure for recognizing plot
  112.    files in which the bytes of two byte integers are reversed.  We can
  113.    recognize these files by looking for size commands containing these
  114.    known sizes in byte reversed form. The last entry should be 0. */
  115.    
  116. int known_size[32] = {
  117.   504,                /* plot3d output 504x504 */
  118.   2048,                /* versatek plotter 2048x2048 */
  119.   2100,                /* plot3d output */
  120.   3120,                /* Tektronix 4010 terminal 3120x3120 */
  121.   4096,                /* GSI 300 terminal 4096x4096 */
  122.   0                /* the last entry should be 0 */
  123.   };
  124.  
  125. /* find_byte_order takes four integer arguments and matches third one
  126.    against a set of known values (sizes, see above). If there is a match
  127.    it merely returns.  If there is no match, it check each of the values
  128.    again with the bottom two bytes reversed. If such a match is found, the
  129.    bottom two bytes of each argument is reversed, the high_byte_first flag
  130.    is inverted to indicated how two byte integers should be read and the
  131.    runction returns. */
  132.    
  133. void
  134. find_byte_order (x0, y0, x1, y1)
  135.      int *x0, *y0, *x1, *y1;
  136. {
  137.   int i;
  138.   for (i=0; known_size[i]!=0; i++)
  139.     {
  140.       if (*x1 == known_size[i])
  141.     return;
  142.     }
  143.   /* now check to see if reversing the bytes allows a match... */
  144.   for (i=0; known_size[i]!=0; i++)
  145.     {
  146.       if (*x1 == swap_bytes (known_size[i]))
  147.     {
  148.       *x0 = swap_bytes( *x0);
  149.       *y0 = swap_bytes( *y0);
  150.       *x1 = swap_bytes( *x1);
  151.       *y1 = swap_bytes( *y1);
  152.       high_byte_first = ! high_byte_first;
  153.       return;
  154.     }
  155.     }
  156.  
  157.   /* finally, if none of this works, just assume that x1 > 128. */
  158.   if ((*x1 < 128) && (swap_bytes (*x1) > 128))
  159.     {
  160.       *x0 = swap_bytes( *x0);
  161.       *y0 = swap_bytes( *y0);
  162.       *x1 = swap_bytes( *x1);
  163.       *y1 = swap_bytes( *y1);
  164.       high_byte_first = ! high_byte_first;
  165.       return;
  166.     }
  167. }
  168.  
  169. /* Read a byte */
  170.  
  171. #define read_byte(stream) (getc (stream))
  172.  
  173. /* Read a coordinate - a two byte integer. */
  174.   
  175. int coord (input)
  176.      FILE *input;
  177. {
  178.   int x;
  179.   if (ascii_input)
  180.     fscanf (input, " %d", &x);
  181.   else
  182.     {
  183.       if ( high_byte_first )
  184.     {
  185.       x = ((char) read_byte (input)) << 8; /* get sign from high byte */
  186.       x |= read_byte (input) & 0xFF; /* not from low byte */
  187.     }
  188.       else
  189.     {
  190.       x = read_byte (input) & 0xFF; /* ingnore sign in low byte */
  191.       x |= ((char) read_byte (input)) << 8; /* get sign from high byte */
  192.     }
  193.       if ( ! signed_input )
  194.     {
  195.       x &= 0xFFFF;
  196.     }
  197.     }
  198.   return x;
  199. }
  200.   
  201. /*  Read a string, change termination to null.
  202.     note: string (buffer) reads a newline terminated string. */
  203.  
  204. void
  205. read_string (input, buffer, buffer_length)
  206.      FILE *input;
  207.      char *buffer;
  208.      int buffer_length;
  209. {
  210.   int length=0;
  211.   char termination = '\n';
  212.   char c = '\0';
  213.  
  214.   while (!feof (input))
  215.     {
  216.       if (length > buffer_length)
  217.     {
  218.       buffer_length *= 2;
  219.       buffer = (char *) realloc (buffer, buffer_length);
  220.       if (buffer <= (char *) 0)
  221.         {
  222.           perror ("realloc failed:");
  223.           exit (-1);
  224.         }
  225.     }
  226.       c = read_byte (input);
  227.       if (c == termination)
  228.     break;
  229.       buffer [length++] = c;
  230.     }
  231.  
  232.   buffer [length] = '\0';    /*  null terminate label */
  233. }
  234.  
  235. /* read_plot reads a plot file from the standard input and calls
  236.    a plot function according to each plot instruction found in the
  237.    file. */
  238.  
  239. void
  240. read_plot (in_stream, buffer, buffer_length)
  241.      FILE *in_stream;
  242.      char *buffer;
  243.      int  buffer_length;
  244. {
  245.   char x_adjust, y_adjust;
  246.   int x0, y0, x1, y1, x2, y2;
  247.   int instruction;
  248.  
  249.   instruction = read_byte (in_stream);
  250.   while (!feof (in_stream))
  251.     {
  252.       switch (instruction)
  253.     {
  254.       /*  Note: we must get all but the last argument before calling to
  255.           ensure reading them in the proper order. */
  256.       
  257.     case ALABEL:
  258.       x_adjust = read_byte (in_stream);
  259.       y_adjust = read_byte (in_stream); 
  260.       read_string (in_stream, buffer, buffer_length);
  261.       if (backward_compatible)
  262.         label (buffer);
  263.       else
  264.         alabel (x_adjust, y_adjust, buffer);
  265.       break;
  266.     case ARC:
  267.       x0 = coord (in_stream);
  268.       y0 = coord (in_stream);
  269.       x1 = coord (in_stream);
  270.       y1 = coord (in_stream); 
  271.       x2 = coord (in_stream);
  272.       y2 = coord (in_stream); 
  273.       arc (x0, y0, x1, y1, x2, y2);
  274.       break;
  275.     case CIRCLE:
  276.       x0 = coord (in_stream);
  277.       y0 = coord (in_stream);
  278.       x1 = coord (in_stream);
  279.       circle (x0, y0, x1);
  280.       break;
  281.     case COLOR:
  282.       x0 = coord (in_stream);
  283.       y0 = coord (in_stream);
  284.       x1 = coord (in_stream);
  285.       if (!backward_compatible)
  286.         color (x0, y0, x1);
  287.       break;
  288.     case COMMENT:
  289.       read_string (in_stream, buffer, buffer_length);
  290.       break;
  291.     case CONT:
  292.       x0 = coord (in_stream);
  293.       y0 = coord (in_stream);
  294.       cont (x0, y0);
  295.       break;
  296.     case ERASE:
  297.       erase ();
  298.       break;
  299.     case FILL:
  300.       x0 = coord (in_stream);
  301.       if (!backward_compatible)
  302.         fill (x0);
  303.       break;
  304.     case FONT:
  305.       read_string (in_stream, buffer, buffer_length);
  306.       if (!backward_compatible)
  307.         fontname (buffer);
  308.       break;
  309.     case FONTSIZE:
  310.       x0 = coord (in_stream);
  311.       if (!backward_compatible)
  312.         fontsize (x0);
  313.       break;
  314.     case LABEL:
  315.       read_string (in_stream, buffer, buffer_length);
  316.       label (buffer);
  317.       break;
  318.     case LINE:
  319.       x0 = coord (in_stream);
  320.       y0 = coord (in_stream);
  321.       x1 = coord (in_stream);
  322.       y1 = coord (in_stream); 
  323.       line (x0, y0, x1, y1);
  324.       break;
  325.     case LINEMOD:
  326.       read_string (in_stream, buffer, buffer_length);
  327.       linemod (buffer);
  328.       break;
  329.     case MOVE:
  330.       x0 = coord (in_stream);
  331.       y0 = coord (in_stream);
  332.       move (x0, y0);
  333.       break;
  334.     case POINT:
  335.       x0 = coord (in_stream);
  336.       y0 = coord (in_stream);
  337.       point (x0, y0);
  338.       break;
  339.     case ROTATE:
  340.       x0 = coord (in_stream);
  341.       y0 = coord (in_stream);
  342.       x1 = coord (in_stream);
  343.       if (!backward_compatible)
  344.         rotate (x0, y0, x1);
  345.       break;
  346.     case SPACE:
  347.       x0 = coord (in_stream);
  348.       y0 = coord (in_stream);
  349.       x1 = coord (in_stream);
  350.       y1 = coord (in_stream); 
  351.       if (guess_byte_order)
  352.         find_byte_order(&x0, &y0, &x1, &y1);
  353.       space (x0, y0, x1, y1);
  354.       break;
  355.         case '\n':
  356.       if (ascii_input)
  357.         break;
  358.     default:
  359.       fprintf (stderr, "Unrecognized plot command `%c' ignored.\n", instruction);
  360.     }
  361.       instruction = read_byte (in_stream);
  362.     }
  363.   return;
  364. }
  365.  
  366.  
  367. void
  368. read_plot_ascii_out (in_stream, buffer, buffer_length)
  369.      FILE *in_stream;
  370.      char *buffer;
  371.      int  buffer_length;
  372. {
  373.   char x_adjust, y_adjust;
  374.   int x0, y0, x1, y1, x2, y2;
  375.   int instruction;
  376.  
  377.   instruction = read_byte (in_stream);
  378.   while (!feof (in_stream))
  379.     {
  380.       switch (instruction)
  381.     {
  382.       /*  Note: we must get all but the last argument before calling to
  383.           ensure reading them in the proper order. */
  384.       
  385.     case ALABEL:
  386.       x_adjust = read_byte (in_stream);
  387.       y_adjust = read_byte (in_stream); 
  388.       read_string (in_stream, buffer, buffer_length);
  389.       if (backward_compatible)
  390.         printf("%c%s\n", LABEL, buffer);
  391.       else
  392.         printf("%c%c%c%s\n", ALABEL, x_adjust, y_adjust, buffer);
  393.       break;
  394.     case ARC:
  395.       x0 = coord (in_stream);
  396.       y0 = coord (in_stream);
  397.       x1 = coord (in_stream);
  398.       y1 = coord (in_stream); 
  399.       x2 = coord (in_stream);
  400.       y2 = coord (in_stream); 
  401.       printf("%c %d %d %d %d %d %d\n", ARC, x0, y0, x1, y1, x2, y2);
  402.       break;
  403.     case CIRCLE:
  404.       x0 = coord (in_stream);
  405.       y0 = coord (in_stream);
  406.       x1 = coord (in_stream);
  407.       printf("%c %d %d %d\n", CIRCLE, x0, y0, x1);
  408.       break;
  409.     case COLOR:
  410.       x0 = coord (in_stream);
  411.       y0 = coord (in_stream);
  412.       x1 = coord (in_stream);
  413.       if (!backward_compatible)
  414.       printf("%c %d %d %d\n", COLOR, x0, y0, x1);
  415.       break;
  416.     case CONT:
  417.       x0 = coord (in_stream);
  418.       y0 = coord (in_stream);
  419.       printf("%c %d %d\n", CONT, x0, y0);
  420.       break;
  421.     case ERASE:
  422.       printf("%c\n", ERASE, buffer);
  423.       break;
  424.     case FILL:
  425.       x0 = coord (in_stream);
  426.       if (!backward_compatible)
  427.         printf("%c %d\n", FILL, x0);
  428.       break;
  429.     case FONT:
  430.       read_string (in_stream, buffer, buffer_length);
  431.       if (!backward_compatible)
  432.         printf("%c%s\n", FONT, buffer);
  433.       break;
  434.     case FONTSIZE:
  435.       x0 = coord (in_stream);
  436.       if (!backward_compatible)
  437.         printf("%c %d\n", FONTSIZE, x0);
  438.       break;
  439.     case LABEL:
  440.       read_string (in_stream, buffer, buffer_length);
  441.       printf("%c%s\n", LABEL, buffer);
  442.       break;
  443.     case LINE:
  444.       x0 = coord (in_stream);
  445.       y0 = coord (in_stream);
  446.       x1 = coord (in_stream);
  447.       y1 = coord (in_stream); 
  448.       printf("%c %d %d %d %d\n", LINE, x0, y0, x1, y1);
  449.       break;
  450.     case LINEMOD:
  451.       read_string (in_stream, buffer, buffer_length);
  452.       printf("%c%s\n", LINEMOD, buffer);
  453.       break;
  454.     case MOVE:
  455.       x0 = coord (in_stream);
  456.       y0 = coord (in_stream);
  457.       printf("%c %d %d\n", MOVE, x0, y0);
  458.       break;
  459.     case POINT:
  460.       x0 = coord (in_stream);
  461.       y0 = coord (in_stream);
  462.       printf("%c %d %d\n", POINT, x0, y0);
  463.       break;
  464.     case ROTATE:
  465.       x0 = coord (in_stream);
  466.       y0 = coord (in_stream);
  467.       x1 = coord (in_stream);
  468.       if (!backward_compatible)
  469.         printf("%c %d %d %d\n", ROTATE, x0, y0, x1);
  470.       break;
  471.     case SPACE:
  472.       x0 = coord (in_stream);
  473.       y0 = coord (in_stream);
  474.       x1 = coord (in_stream);
  475.       y1 = coord (in_stream); 
  476.       if (guess_byte_order)
  477.         find_byte_order(&x0, &y0, &x1, &y1);
  478.       printf("%c %d %d %d %d\n", SPACE, x0, y0, x1, y1);
  479.       break;
  480.         case '\n':
  481.       if (ascii_input)
  482.         break;
  483.     default:
  484.       fprintf (stderr, "Unrecognized plot command `%c' ignored.\n", instruction);
  485.     }
  486.       instruction = read_byte (in_stream);
  487.     }
  488.   return;
  489. }
  490.  
  491. void
  492. display_version()
  493. {
  494.     (void) fprintf (stderr, "\
  495. plot2plot version %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\
  496. plot2plot comes with ABSOLUTELY NO WARRANTY; type `plot2plot +warranty'\n\
  497. for details.  This is free software, and you are welcome to redistribute\n\
  498. it; Type `plot2plot +copying' to view the copying conditions.\n",
  499.             VERS);
  500. }
  501.  
  502. void
  503.   display_help()
  504. {
  505.     (void) fprintf(stderr, "\
  506. Usage:  plot2plot [-biohlsuCHVW]\n\
  507.         [+backward-compatible] [+input-is-ascii] [+output-as-ascii]\n\
  508.         [+high-byte-first] [+low-byte-first] [+signed-input]\n\
  509.         [+unsigned-input] [+copying] [+help] [+version] [+warranty]\n\
  510.         [data_files]\n");
  511. }
  512.  
  513.  
  514. int
  515. main (argc, argv)
  516.      int argc;
  517.      char *argv[];
  518. {
  519.   char *buffer;
  520.   int  buffer_length;
  521.   int  opened=0;        /* remember whether we have opened output. */
  522.   int  show_help = 0;        /* remember to show a help message */
  523.   int  show_version = 0;    /* remember to show the version */
  524.   int  show_copying = 0;    /* remember to show the copying message */
  525.   int  errcnt = 0;
  526.   int  option;            /* Option character */
  527.   int  opt_index;        /* Long option index */
  528.  
  529.   buffer_length = 1024;
  530.   buffer = (char *) malloc (buffer_length);
  531.   if (buffer <= (char *) 0)
  532.     {
  533.       perror ("malloc failed:");
  534.       exit (-1);
  535.     }
  536.  
  537.   while ((option = getopt_long(argc, argv, "CHVWbiohlsu", long_options, &opt_index)) != EOF) {
  538.       if (option == 0)
  539.     option = long_options[opt_index].val;
  540.  
  541.       switch (option) {
  542.       case 'b':        /* Backward compatible */
  543.       backward_compatible = 1;
  544.       break;
  545.       case 'i':        /* Ascii input    */
  546.       ascii_input = 1;
  547.       break;
  548.       case 'o':        /* Ascii output */
  549.       ascii_output = 1;
  550.       break;
  551.       case 'h':        /* High byte first */
  552.       guess_byte_order = 0;
  553.       high_byte_first = 1;
  554.       break;
  555.       case 'l':        /* Low byte first */
  556.       guess_byte_order = 0;
  557.       high_byte_first = 0;
  558.       break;
  559.       case 's':        /* Signed */
  560.       signed_input = 1;
  561.       break;
  562.       case 'u':        /* Unsigned */
  563.       signed_input = 0;
  564.       break;
  565.       case 'H':        /* Help */
  566.       show_help = 1;
  567.       break;
  568.       case 'V':        /* Version */
  569.       show_version = 1;
  570.       break;
  571.       case 'W':        /* Warranty */
  572.       case 'C':        /* Copying */
  573.       show_copying = 1;
  574.       break;
  575.       default:
  576.       errcnt++;
  577.       break;
  578.       }
  579.   }
  580.  
  581.   if (show_version)
  582.     display_version();
  583.  
  584.   if (errcnt > 0 || show_help)
  585.     display_help();
  586.  
  587.  
  588.   if (show_copying) {
  589.       int k;
  590.       
  591.       if (!show_version)
  592.     display_version();
  593.       for (k = 0; copy_notice[k] != '\0'; k++) {
  594.       (void) fputs(copy_notice[k], stderr);
  595.       }
  596.       exit(0);
  597.   }
  598.  
  599.   if (errcnt > 0 || show_help)
  600.     exit(errcnt > 0 ? 1 : 0);
  601.   
  602.   if (optind >= argc) {
  603.       /* Read from stdin */
  604.  
  605.       if (ascii_output)
  606.     read_plot_ascii_out(stdin, buffer, buffer_length);
  607.       else
  608.     read_plot(stdin, buffer, buffer_length);
  609.       opened++;
  610.       openpl();
  611.   } else {
  612.       FILE    *filep;
  613.  
  614.       for ( ; optind < argc; optind++) {
  615.       if (strcmp(argv[optind], "-") == 0) {
  616.           filep = stdin;
  617.       } else {
  618.           filep = fopen(argv[optind], "r");
  619.           if (filep == NULL) {
  620.           (void) fprintf(stderr, "%s:  inaccessible or nonexistent file ignored:  `%s'\n",
  621.                  argv[0], argv[optind]);
  622.           } else {
  623.           if (opened++)
  624.             openpl();
  625.           if (ascii_output)
  626.             read_plot_ascii_out(filep, buffer, buffer_length);
  627.           else
  628.             read_plot(filep, buffer, buffer_length);
  629.           /* Close the file, but not if it's stdin */
  630.           if (filep != stdin)
  631.             fclose(filep);
  632.           }
  633.       }
  634.       }    /* endfor */
  635.   }
  636.       
  637.  
  638.   if (opened)
  639.     closepl();
  640.  
  641.   return 0;
  642. }
  643.